package com.example.spring.security.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.annotation.Resource;

/**
 * @author : zhayh
 * @date : 2021-4-17 17:42
 * @description : Spring Security配置类
 */

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Resource
    private UserDetailsService userService;

    @Bean
    PasswordEncoder passwordEncoder() {
        // 指定密码加密方法，加盐哈希
        return new BCryptPasswordEncoder();
    }

    // 基于内存的认证，配置用户及对应的角色
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 基于内存的身份认证
//        auth.inMemoryAuthentication()
//                .withUser("admin").password(passwordEncoder().encode("123")).roles("vip", "user")
//                .and()
//                .withUser("vip").password(passwordEncoder().encode("123")).roles("vip", "user")
//                .and()
//                .withUser("user").password(passwordEncoder().encode("123")).roles("user");

        // 使用UserDetailsService进行身份认证
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }

    // 授权，配置URL访问权限
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests() // 开启HttpSecurity配置
                // 对static文件夹下的静态资源统一放行
                .antMatchers("/login/**").permitAll()
                .antMatchers("/detail/user/**").hasRole("user")
                .antMatchers("/detail/vip/**").hasRole(("vip"))
                .anyRequest().authenticated()  // 其它请求登录之后都能访问
                .and()
                .formLogin() // 登录表单页面的配置
                // 自定义用户登录
                .loginPage("/doLogin").permitAll() // 登录页面跳转路径，默认是get方式的/login
                .loginProcessingUrl("/doLogin") // 登录表单提交的路径，默认是post方式的/login
                .usernameParameter("username")
                .passwordParameter("password")
                .defaultSuccessUrl("/")
                .failureUrl("/login?error")
//                // 登录成功返回JSON字符串
//                .successHandler(new AuthenticationSuccessHandler() {
//                    @Override
//                    public void onAuthenticationSuccess(HttpServletRequest request,
//                                                        HttpServletResponse response,
//                                                        Authentication auth) throws IOException, ServletException {
//                        Object principal = auth.getPrincipal();
//                        response.setContentType("application/json;charset-utf-8");
//                        PrintWriter out = response.getWriter();
//                        response.setStatus(200);
//                        HashMap<String, Object> map = new HashMap<>();
//                        map.put("status", 200);
//                        map.put("msg", principal);
//                        ObjectMapper objMapper = new ObjectMapper();
//                        out.write(objMapper.writeValueAsString(map));
//                        out.flush();
//                        out.close();
//                    }
//                })
//                // 登录失败返回JSON字符串
//                .failureHandler(new AuthenticationFailureHandler() {
//                    @Override
//                    public void onAuthenticationFailure(HttpServletRequest request,
//                                                        HttpServletResponse response,
//                                                        AuthenticationException e) throws IOException,
//                                                        ServletException {
//                        response.setContentType("application/json;charset-utf-8");
//                        PrintWriter out = response.getWriter();
//                        response.setStatus(401);
//                        HashMap<String, Object> map = new HashMap<>();
//                        map.put("status", 401);
//                        if (e instanceof LockedException) {
//                            map.put("msg", "账户被锁定，登录失败");
//                        } else if (e instanceof BadCredentialsException) {
//                            map.put("msg", "账户名或密码错误，登录失败");
//                        } else if (e instanceof DisabledException) {
//                            map.put("msg", "账户被禁用，登录失败");
//                        } else if (e instanceof AccountExpiredException) {
//                            map.put("msg", "账户已过期，登录失败");
//                        } else if (e instanceof CredentialsExpiredException) {
//                            map.put("msg", "密码已过期，登录失败");
//                        } else{
//                            map.put("msg", "登录失败");
//                        }
//                        ObjectMapper objMapper = new ObjectMapper();
//                        out.write(objMapper.writeValueAsString(map));
//                        out.flush();
//                        out.close();
//                    }
//                })
//                .permitAll()
                .and()
                // 自定义注销功能
                .logout().logoutUrl("/logout").logoutSuccessUrl("/")
                .and().csrf().disable();  // 关闭防csrf攻击
    }
}
